
//
//  EventHandler.m
//  libNiblvl50_EventBus
//
//  Created by Niblit on 2010-02-19.
//  Copyright 2010 Nib_lvl50. All rights reserved.
//

#import "EventHandler.h"


@implementation EventHandler

//!
//! The actual instance of the EventHandler
//!
static EventHandler* instance = nil;


+(EventHandler*) getInstance
{
	@synchronized(self)
	{
		if(instance == nil)
		{
			instance = [[self alloc] init];
		}
	}
	
	return instance;
}

+(id) allocWithZone:(NSZone*)zone
{
	@synchronized(self)
	{
		if(instance == nil)
		{
			instance = [super allocWithZone:zone];
			return instance;
		}
	}
	
	return nil;
}

-(id) init
{
	self = [super init];
	mEventListeners = [[NSMutableDictionary alloc] init];
	
	return self;
}

-(void) AddListener:(id)listener withSelector:(SEL)selector forEvent:(Class)eventClass
{
	@synchronized(self)
	{
		if([listener respondsToSelector:selector] == NO)
		{
			[NSException raise:@"SelectorNotCompatible_Exception" format:@"The listener does not respond to the selector provided"];
		}
		
		NSMethodSignature* signature = [listener methodSignatureForSelector:selector];
		NSInvocation* invoker = [NSInvocation invocationWithMethodSignature:signature];
		invoker.selector = selector;
		invoker.target = listener;
	
		NSMutableArray* theArray = [mEventListeners objectForKey:eventClass];
	
		if(theArray == nil)
		{
			theArray = [[NSMutableArray alloc] init];
			[theArray addObject:invoker];
			[mEventListeners setObject:theArray forKey:eventClass];
			[theArray release];
		}
		else
		{
			for(int index = 0; index < theArray.count; ++index)
			{
				NSInvocation* invoker = [theArray objectAtIndex:index];
				if(invoker.target == listener)
				{
					// The listener is already added, bail out now.
					return;
				}
			}
			
			[theArray addObject:invoker];
		}

	}
}


-(BOOL) RemoveListener:(id)listener forEvent:(Class)eventClass
{
	@synchronized(self)
	{
		NSMutableArray* theArray = [mEventListeners objectForKey:eventClass];
		
		if(theArray == nil)
		{
			return FALSE;
		}
		
		for(int index = 0; index < theArray.count; ++index)
		{
			NSInvocation* invoker = [theArray objectAtIndex:index];
			if(invoker.target == listener)
			{
				[theArray removeObject:invoker];
				NSLog(@"Removed a listener from EventHandler");
				
				if(theArray.count == 0)
				{
					[mEventListeners removeObjectForKey:eventClass];
				}
				
				return TRUE;
			}
		}
	}
	
	return FALSE;
}


-(void) SendEvent:(id<NSObject>)event
{
	@synchronized(self)
	{
		NSMutableArray* theArray = [mEventListeners objectForKey:event.class];
		
		if(theArray == nil)
		{
			return;
		}
		
		for(int index = 0; index < theArray.count; ++index)
		{
			NSInvocation* invoker = [theArray objectAtIndex:index];
			[invoker setArgument:&event atIndex:2];
			[invoker invoke];
		}
	}
}

-(id) copyWithZone:(NSZone*)zone
{
	return self;
}

-(id) retain
{
	return self;
}

-(NSUInteger) retainCount
{
	return NSUIntegerMax;
}

-(void) release
{
	
}

-(id) autorelease
{
	return self;
}

-(void) dealloc
{
	[mEventListeners release];
	[super dealloc];
}

@end
